package com.tencent.tws.pluginhost.ui;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import tws.component.log.TwsLog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.FrameLayout;
import com.tencent.tws.assistant.app.ActionBar;
import com.tencent.tws.assistant.support.v4.app.Fragment;
import com.tencent.tws.assistant.support.v4.app.FragmentManager;
import com.tencent.tws.assistant.support.v4.app.FragmentPagerAdapter;
import com.tencent.tws.assistant.support.v4.app.FragmentTransaction;
import com.tencent.tws.assistant.support.v4.app.TwsFragmentActivity;
import com.tencent.tws.assistant.widget.Toast;
import com.tencent.tws.framework.HomeUIProxy;
import com.tencent.tws.framework.HostProxy;
import com.tencent.tws.pluginhost.HostApplication;
import com.tencent.tws.pluginhost.R;
import com.tencent.tws.pluginhost.ui.view.CellItem.ActionBarInfo;
import com.tencent.tws.pluginhost.ui.view.CellItem.ComponentName;
import com.tencent.tws.pluginhost.ui.view.Hotseat;
import com.tencent.tws.pluginhost.ui.view.Hotseat.OnHotseatClickListener;
import com.tencent.tws.pluginhost.ui.view.MyWatchFragmentRevision;
import com.tws.plugin.content.DisplayConfig;
import com.tws.plugin.content.LoadedPlugin;
import com.tws.plugin.content.PluginDescriptor;
import com.tws.plugin.core.PluginApplication;
import com.tws.plugin.core.PluginLauncher;
import com.tws.plugin.core.PluginLoader;
import com.tws.plugin.manager.InstallResult;
import com.tws.plugin.manager.PluginCallback;
import com.tws.plugin.manager.PluginManagerHelper;
import com.tws.plugin.util.FileUtil;
import dalvik.system.DexClassLoader;
public class HostHomeActivity extends TwsFragmentActivity implements HomeUIProxy {
private final String TAG = "rick_Print:HostHomeActivity";
private Hotseat mHotseat;
private OnHotseatClickListener mHotseatClickCallback;
private FragmentPagerAdapter mFragmentPagerAdapter;
private MyWatchFragmentRevision mMyWatchFragment = null;// 这个是DM固有的,直接保留引用就不开回调进行后续同步的操作处理
private FrameLayout mFragmentContainer;
private ArrayList<DisplayInfo> mHotseatDisplayInfos = new ArrayList<DisplayInfo>();
private ArrayList<DisplayInfo> mHomeFragementDisplayInfos = new ArrayList<DisplayInfo>(); // myWatchfaceFragment
private final int POS_HOTSEAT = DisplayConfig.DISPLAY_AT_HOTSEAT;
private final int POS_HOME_FRAGEMENT = DisplayConfig.DISPLAY_AT_HOME_FRAGEMENT;
private final String POS_HOTSEAT_CONFIG_NAME = "plugin_hotseat_pos.ini";
private final String POS_MYWATCH_CONFIG_NAME = "plugin_mywatch_pos.ini";
private HashMap<String, Integer> mPluginHotsetPos = new HashMap<String, Integer>();
private HashMap<String, Integer> mPluginMywatchPos = new HashMap<String, Integer>();
private final int POS_WEIGHT = 5; // 位置信息的权重值
private final int DEPEND_ON_APPLICATION = 1;
private final int DEPEND_ON_PLUGIN = 2;
private HashMap<String, String> mDependOnMap = new HashMap<String, String>();
private int mNormalTextColor;
private int mFocusTextColor;
// private HomeBar mHomeBar;
private ActionBar mActionBar;
private int mBar_rBtnActionType = DisplayConfig.TYPE_ACTIVITY; // 当前默认是activity
private String mBar_rBtnActionContent = null;
// 插件更新监听
private final BroadcastReceiver mPluginChangedMonitor = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final int actionType = intent.getIntExtra(PluginCallback.EXTRA_TYPE, PluginCallback.TYPE_UNKNOW);
final String packageName = intent.getStringExtra(PluginCallback.EXTRA_ID);
final int installRlt = intent.getIntExtra(PluginCallback.EXTRA_RESULT_CODE, -1);
if (TextUtils.isEmpty(packageName)) {// 无效的包名信息
TwsLog.e(TAG, "Receive Invalid information package name");
return;
}
switch (actionType) {
case PluginCallback.TYPE_INSTALL:
if (installRlt == InstallResult.SUCCESS) {
TwsLog.d(TAG, "插件:" + packageName + "安装成功了~");
installPlugin(packageName);
}
break;
case PluginCallback.TYPE_REMOVE:
// success ? 0 : 7
if (installRlt == 0) {// 卸载成功
TwsLog.d(TAG, "插件:" + packageName + "被卸载了哈~");
if (mHotseat == null) {
TwsLog.d(TAG, "貌似mHotseat还没初始化哦"); // 这种情况应该基本不会出现
} else {
removePlugin(packageName);
}
if (mMyWatchFragment == null) {
TwsLog.d(TAG, "貌似MyWatchFragment还没构建出来"); // 这种情况有可能出现哦
} else {
mMyWatchFragment.removePlugin(packageName);
}
}
break;
case PluginCallback.TYPE_REMOVE_ALL:
// success ? 0 : 7
if (installRlt == 0) {// 卸载成功
TwsLog.d(TAG, "~~~~(>_<)~~~~所有插件都被卸载了咯!");
// ~暂不处理,因为DM起来首页显示出来后,应该是不存在这个情况
}
break;
default:
break;
}
}
};
// 应用安装卸载监听
private final BroadcastReceiver mAppUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (TextUtils.equals(intent.getAction(), Intent.ACTION_PACKAGE_ADDED)) {
String packageName = intent.getData().getSchemeSpecificPart();
if (mDependOnMap.containsKey(packageName)) {
String pid = mDependOnMap.get(packageName);
establishedDependOnForPlugin(pid);
}
} else if (TextUtils.equals(intent.getAction(), Intent.ACTION_PACKAGE_REMOVED)) {
String packageName = intent.getData().getSchemeSpecificPart();
if (mDependOnMap.containsKey(packageName)) {
String pid = mDependOnMap.get(packageName);
unEstablishedDependOnForPlugin(pid);
}
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
super.onCreate(savedInstanceState);
// 监听插件更新
registerReceiver(mPluginChangedMonitor, new IntentFilter(PluginCallback.ACTION_PLUGIN_CHANGED));
// 监听应用的安装卸载
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.PACKAGE_ADDED");
filter.addAction("android.intent.action.PACKAGE_REMOVED");
filter.addDataScheme("package");
registerReceiver(mAppUpdateReceiver, filter);
setContentView(R.layout.activity_home);
mHotseat = (Hotseat) findViewById(R.id.home_bottom_tab);
mFragmentContainer = (FrameLayout) findViewById(R.id.home_fragment_container);
initHomeBottomTabObserver();
mNormalTextColor = getResources().getColor(R.color.home_bottom_tab_text_default_color);
mFocusTextColor = getResources().getColor(R.color.home_bottom_tab_text_pressed_color);
initPluginPosFromConfig(POS_HOTSEAT);
initPluginPosFromConfig(POS_HOME_FRAGEMENT);
initPluginsDisplayInfo();
// 初始化底部Hotseat
initHotseat();
HostProxy.setHomeUIProxy(this);
mFragmentPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) {
@Override
public Fragment getItem(int position) {
return getFragmentByTagIndex(position);
}
@Override
public int getCount() {
return mHotseat.childCount();
}
};
initActionBar();
// 默认聚焦位置
final int fouceIndex = mHotseat.getPosByClassId(((HostApplication) HostApplication.getInstance())
.getFouceTabClassId());
switchFragment(mHotseat.setFocusIndex(fouceIndex));
}
private void initHotseat() {
if (mHotseat == null) {
mHotseat = (Hotseat) findViewById(R.id.home_bottom_tab);
}
if (mHotseat == null) {
TwsLog.e(TAG, "initBottomTabView() mHotseat is null");
return;
}
// 添加my watch fragment
mHotseat.addOneBottomButton(Hotseat.HOST_HOME_FRAGMENT, null, Hotseat.FRAGMENT_COMPONENT, getResources()
.getString(R.string.home_my_watch),
getResources().getDrawable(R.drawable.home_bottom_tab_my_watch_default),
getResources().getDrawable(R.drawable.home_bottom_tab_my_watch_pressed), mNormalTextColor,
mFocusTextColor, 0);
// 其他的根据插件配置来
for (DisplayInfo info : mHotseatDisplayInfos) {
// 当前Hotseat上暂时之放置fragment
if (info.componentType != DisplayConfig.TYPE_FRAGMENT) {
continue;
}
mHotseat.addOneBottomButtonForPlugin(info, mNormalTextColor, mFocusTextColor, false);
}
}
private void initHomeBottomTabObserver() {
mHotseatClickCallback = new OnHotseatClickListener() {
@Override
public void onItemClick(int index) {
TwsLog.d(TAG, "onItemClick:" + index);
switchFragment(index);
}
@Override
public void updateActionBar(ActionBarInfo actionBarInfo) {
mActionBar.setTitle(actionBarInfo.ab_title);
TwsLog.d(TAG, "updateActionBar:" + actionBarInfo.toString());
if (TextUtils.isEmpty(actionBarInfo.ab_rbtncontent)) {// 不需要右侧按钮
mActionBar.getRightButtonView().setImageResource(R.color.transparent);
mActionBar.getRightButtonView().setClickable(false);
} else if (actionBarInfo.ab_rbtnrestype == DisplayConfig.ACTIONBAR_RBTN_TYPE_ICON) {
mActionBar.getRightButtonView().setVisibility(View.VISIBLE);
mActionBar.getRightButtonView().setClickable(true);
final String resName = actionBarInfo.ab_rbtnres_normal + "_" + actionBarInfo.ab_rbtnres_focus;
Drawable drawable = PluginManagerHelper.getPluginIcon(resName);
if (drawable != null) {
mActionBar.getRightButtonView().setImageDrawable(drawable);
} else {
final Drawable normal = PluginManagerHelper.getPluginIcon(actionBarInfo.ab_rbtnres_normal);
if (TextUtils.isEmpty(actionBarInfo.ab_rbtnres_normal) || normal == null) {
mActionBar.getRightButtonView().setImageResource(R.drawable.ic_launcher);
} else if (actionBarInfo.ab_rbtnres_normal.equals(actionBarInfo.ab_rbtnres_focus)) {
mActionBar.getRightButtonView().setImageDrawable(normal);
} else {
final Drawable focus = PluginManagerHelper.getPluginIcon(actionBarInfo.ab_rbtnres_normal);
if (focus == null) {
mActionBar.getRightButtonView().setImageDrawable(normal);
} else {
StateListDrawable stateListDrawable = new StateListDrawable();
stateListDrawable.addState(new int[] { android.R.attr.state_pressed },
PluginManagerHelper.getPluginIcon(actionBarInfo.ab_rbtnres_focus));
stateListDrawable.addState(new int[] {}, normal);
PluginManagerHelper.addPluginIcon(resName, stateListDrawable);
mActionBar.getRightButtonView().setImageDrawable(stateListDrawable);
}
}
}
mBar_rBtnActionContent = actionBarInfo.ab_rbtncontent;
mBar_rBtnActionType = actionBarInfo.ab_rbtnctype;
} else {
// 略
}
}
@Override
public void onItemClick(int tagIndex, int extras) {
TwsLog.d(TAG, "onItemClick:" + tagIndex);
switchFragment(tagIndex, extras);
}
};
mHotseat.addHotseatClickObserver(mHotseatClickCallback);
}
private void initActionBar() {
mActionBar = getTwsActionBar();
mActionBar.getActionBarHome().setVisibility(View.GONE);
mActionBar.getRightButtonView().setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
handleActionBarRightButtonClick();
}
});
mActionBar.getRightButtonView().setClickable(false);
}
private void handleActionBarRightButtonClick() {
Intent intent = new Intent();
intent.setClassName(this, mBar_rBtnActionContent);
switch (mBar_rBtnActionType) {
case DisplayConfig.TYPE_ACTIVITY:
startActivity(intent);
break;
default:
break;
}
}
private void installPlugin(String packageName) {
PluginDescriptor pluginDescriptor = PluginManagerHelper.getPluginDescriptorByPluginId(packageName);
if (null == pluginDescriptor || TextUtils.isEmpty(pluginDescriptor.getPackageName())) {
Toast.makeText(getApplicationContext(), "怎会存在没packageName的插件咧???", Toast.LENGTH_SHORT).show();
Exception here = new Exception();
here.fillInStackTrace();
TwsLog.e(TAG, "My god !!! how can have such a situatio~!:" + packageName, here);
return;
}
if (PluginApplication.getInstance().getEliminatePlugins().contains(pluginDescriptor.getPackageName())) {
TwsLog.w(TAG, "当前插件" + pluginDescriptor.getPackageName() + "已经被列入黑名单了");
return;
}
boolean establishedDependOn = establishedDependOns(pluginDescriptor.getPackageName(),
pluginDescriptor.getDependOns());
final ArrayList<DisplayConfig> dcs = pluginDescriptor.getDisplayConfigs();
if (dcs != null && 0 < dcs.size()) {
String iconDir = new File(pluginDescriptor.getInstalledPath()).getParent() + File.separator
+ FileUtil.ICON_FOLDER;
for (DisplayConfig dc : dcs) {
DisplayInfo info = new DisplayInfo(dc, pluginDescriptor.getPackageName());
info.establishedDependOn = establishedDependOn;
loadPluginIcon(info, pluginDescriptor, dc.pos == DisplayConfig.DISPLAY_AT_HOTSEAT, iconDir);
switch (dc.pos) {
case DisplayConfig.DISPLAY_AT_HOTSEAT: // 显示在Hotseat上
// 当前Hotseat上暂时之放置fragment
if (info.componentType != DisplayConfig.TYPE_FRAGMENT) {
break;
}
mHotseat.addOneBottomButtonForPlugin(info, mNormalTextColor, mFocusTextColor, true);
break;
case DisplayConfig.DISPLAY_AT_HOME_FRAGEMENT: // 显示在host_home_fragement
// mHomeFragementDisplayInfos.add(info);
mMyWatchFragment.addContentItem(info);
break;
case DisplayConfig.DISPLAY_AT_OTHER_POS:// 显示在其他位置
switch (info.componentType) {
case DisplayConfig.TYPE_SERVICE:
Intent intent = new Intent();
intent.setClassName(HostHomeActivity.this, info.classId);
startService(intent);
break;
case DisplayConfig.TYPE_PACKAGENAEM:
if (null == PluginLauncher.instance().startPlugin(info.classId)) {
Toast.makeText(HostHomeActivity.this, "startPlugin:" + info.classId + "失败!!!",
Toast.LENGTH_LONG).show();
}
break;
default:
break;
}
break;
case DisplayConfig.DISPLAY_AT_MENU: // 这个当前没有,暂不处理
default:
break;
}
}
} else {
Toast.makeText(getApplicationContext(), "插件:" + pluginDescriptor.getApplicationName() + "没配置显示协议",
Toast.LENGTH_SHORT).show();
}
}
private void removePlugin(String packageName) {
TwsLog.d(TAG, "removePlugin:" + packageName);
int removeTagIndex = mHotseat.removePlugin(packageName);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
String name = makeFragmentName(mFragmentContainer.getId(), mFragmentPagerAdapter.getItemId(removeTagIndex));
Fragment fragment = fragmentManager.findFragmentByTag(name);
if (fragment != null) {
TwsLog.d(TAG, "removePlugin removeTagIndex=" + removeTagIndex);
transaction.remove(fragment);
// transaction.commit();
// rick_Note:这里被删除的fragment需要做清理操作哈~
}
}
private void establishedDependOnForPlugin(String pid) {
mHotseat.establishedDependOnForPlugin(pid);
mMyWatchFragment.establishedDependOnForPlugin(pid);
}
private void unEstablishedDependOnForPlugin(String pid) {
mHotseat.unEstablishedDependOnForPlugin(pid);
mMyWatchFragment.unEstablishedDependOnForPlugin(pid);
}
// 这个函数同步FragmentPagerAdapter,建议直接用FragmentPagerAdapter里面的接口
private String makeFragmentName(int viewId, long id) {
return "android:switcher:" + viewId + ":" + id;
}
private void switchFragment(int tagIndex) {
if (tagIndex < 0) {
TwsLog.e(TAG, "我的乖乖,怎么会有位置是:" + tagIndex + " 的内容可以切换咧,得check一下是否Hotseat没有内容?");
return;
}
TwsLog.d(TAG, "switchFragment:" + tagIndex);
Fragment fragment = (Fragment) mFragmentPagerAdapter.instantiateItem(mFragmentContainer, tagIndex);
mFragmentPagerAdapter.setPrimaryItem(mFragmentContainer, tagIndex, fragment);
mFragmentPagerAdapter.finishUpdate(mFragmentContainer);
}
private void switchFragment(int tagIndex, int extras) {
if (tagIndex < 0) {
TwsLog.e(TAG, "我的乖乖,怎么会有位置是:" + tagIndex + " 的内容可以切换咧,得check一下是否Hotseat没有内容?");
return;
}
TwsLog.d(TAG, "switchFragment:" + tagIndex);
Fragment fragment = (Fragment) mFragmentPagerAdapter.instantiateItem(mFragmentContainer, tagIndex);
fragment.acceptExtras(extras);
mFragmentPagerAdapter.setPrimaryItem(mFragmentContainer, tagIndex, fragment);
mFragmentPagerAdapter.finishUpdate(mFragmentContainer);
}
/**
* 收集内容: String classId int componentType CharSequence text int
* bkNormalResId, int bkFocusResId
*/
private void initPluginsDisplayInfo() {
// 底部Hotseat 以及 首页watchFragment的内容是有顺序的
mHotseatDisplayInfos.clear();
mHomeFragementDisplayInfos.clear();
// mOtherPosDisplayInfos.clear();
Collection<PluginDescriptor> plugins = PluginManagerHelper.getPlugins();
Iterator<PluginDescriptor> itr = plugins.iterator();
boolean hasGetHotSeatPos = false;
while (itr.hasNext()) {
final PluginDescriptor pluginDescriptor = itr.next();
if (TextUtils.isEmpty(pluginDescriptor.getPackageName())) {
Log.e(TAG, "My god !!! how can have such a situatio~!");
continue;
}
if (PluginApplication.getInstance().getEliminatePlugins().contains(pluginDescriptor.getPackageName())) {
TwsLog.w(TAG, "当前插件" + pluginDescriptor.getPackageName() + "已经被列入黑名单了");
continue;
}
boolean establishedDependOn = establishedDependOns(pluginDescriptor.getPackageName(),
pluginDescriptor.getDependOns());
final ArrayList<DisplayConfig> dcs = pluginDescriptor.getDisplayConfigs();
if (dcs != null && 0 < dcs.size()) {
hasGetHotSeatPos = false;
String iconDir = new File(pluginDescriptor.getInstalledPath()).getParent() + File.separator
+ FileUtil.ICON_FOLDER;
for (DisplayConfig dc : dcs) {
DisplayInfo info = new DisplayInfo(dc, pluginDescriptor.getPackageName());
info.establishedDependOn = establishedDependOn;
loadPluginIcon(info, pluginDescriptor, dc.pos == DisplayConfig.DISPLAY_AT_HOTSEAT, iconDir);
switch (dc.pos) {
case DisplayConfig.DISPLAY_AT_HOTSEAT: // 显示在Hotseat上
if (!hasGetHotSeatPos) {
mHotseatDisplayInfos.add(info);
hasGetHotSeatPos = true;
} else {
TwsLog.e(TAG, "哦~——~哦,插件:" + pluginDescriptor.getPackageName()
+ " 竟然有两个在Hotseat的Pos位,需要框架做一点点的扩展兼容哈。");
}
break;
case DisplayConfig.DISPLAY_AT_HOME_FRAGEMENT: // 显示在host_home_fragement
mHomeFragementDisplayInfos.add(info);
break;
case DisplayConfig.DISPLAY_AT_OTHER_POS:// 显示在其他位置
// mOtherPosDisplayInfos.add(info);
// 这个时机已经调整到application的onCreate了
break;
case DisplayConfig.DISPLAY_AT_MENU: // 这个当前没有,暂不处理
default:
break;
}
}
} else {
Log.e(TAG, "插件:" + pluginDescriptor.getPackageName() + "没有配置plugin-display协议~");
}
}
}
private boolean establishedDependOns(String pid, ArrayList<String> dependOns) {
// 依赖检测
if (dependOns == null || dependOns.size() <= 0) {
return true;
}
// 当前这种依赖只处理一个
String dependOnDes = dependOns.get(0);
if (TextUtils.isEmpty(dependOnDes))
return true;
final String[] values = dependOnDes.split(DisplayConfig.SEPARATOR_DEPEND);
TwsLog.d(TAG, "establishedDependOn:" + dependOnDes);
String packageName = null;
int type = DEPEND_ON_APPLICATION;
if (values.length == 1) {
packageName = values[0];
type = DEPEND_ON_APPLICATION;
} else if (values.length == 2) {
type = Integer.parseInt(values[0]);
packageName = values[1];
} else {
Toast.makeText(this, "", Toast.LENGTH_SHORT).show();
}
switch (type) {
case DEPEND_ON_APPLICATION:
if (mDependOnMap.containsKey(packageName)) {
String des = "插件:" + pid + "所依赖的:" + packageName + "条件,还有插件:" + mDependOnMap.get(packageName)
+ "也依赖这个条件";
Toast.makeText(this, des, Toast.LENGTH_LONG).show();
TwsLog.d(TAG, des);
}
mDependOnMap.put(packageName, pid);
TwsLog.d(TAG, "mDependOnMap put:" + packageName + " " + pid);
if (!dependOnInstalledApp(packageName)) {
return false;
}
break;
case DEPEND_ON_PLUGIN:
break;
default:
break;
}
return true;
}
private boolean dependOnInstalledApp(String packagename) {
// String packagename = "com.qding.community";
PackageInfo packageInfo;
try {
packageInfo = getPackageManager().getPackageInfo(packagename, 0);
} catch (NameNotFoundException e) {
packageInfo = null;
e.printStackTrace();
}
if (packageInfo == null) {
return false;
} else {
return true;
}
}
private void loadPluginIcon(final DisplayInfo info, final PluginDescriptor pluginDescriptor, boolean isHotseat,
String iconDir) {
if (TextUtils.isEmpty(info.normalResName)) {
TwsLog.e(TAG, "loadPluginIcon:" + info.normalResName + " failed for Illegal resources name~");
return;
}
String iconPath;
Bitmap normalIcon = null;
if (null == PluginManagerHelper.getPluginIcon(info.normalResName)) {
iconPath = iconDir + File.separator + info.normalResName + FileUtil.FIX_ICON_NAME;
normalIcon = BitmapFactory.decodeFile(iconPath);
if (normalIcon != null) {
PluginManagerHelper.addPluginIcon(info.normalResName, new BitmapDrawable(getResources(), normalIcon));
}
}
if (null == PluginManagerHelper.getPluginIcon(info.focusResName)
&& !info.normalResName.equals(info.focusResName)) {
iconPath = iconDir + File.separator + info.focusResName + FileUtil.FIX_ICON_NAME;
Bitmap focusIcon = BitmapFactory.decodeFile(iconPath);
if (focusIcon != null) {
PluginManagerHelper.addPluginIcon(info.focusResName, new BitmapDrawable(getResources(), focusIcon));
}
}
if (!isHotseat)
return;
if (info.ab_rbtnrestype == DisplayConfig.ACTIONBAR_RBTN_TYPE_ICON && !TextUtils.isEmpty(info.ab_rbtnres_normal)
&& null == PluginManagerHelper.getPluginIcon(info.ab_rbtnres_normal)) {
iconPath = iconDir + File.separator + info.ab_rbtnres_normal + FileUtil.FIX_ICON_NAME;
Bitmap abr_normalIcon = BitmapFactory.decodeFile(iconPath);
if (abr_normalIcon != null) {
PluginManagerHelper.addPluginIcon(info.ab_rbtnres_normal, new BitmapDrawable(getResources(),
abr_normalIcon));
}
if (null == PluginManagerHelper.getPluginIcon(info.ab_rbtnres_focus)
&& !info.ab_rbtnres_normal.equals(info.ab_rbtnres_focus)) {
iconPath = iconDir + File.separator + info.ab_rbtnres_focus + FileUtil.FIX_ICON_NAME;
Bitmap abr_focusIcon = BitmapFactory.decodeFile(iconPath);
if (abr_focusIcon != null) {
PluginManagerHelper.addPluginIcon(info.ab_rbtnres_focus, new BitmapDrawable(getResources(),
abr_focusIcon));
}
}
}
}
private Fragment getFragmentByTagIndex(int tagIndex) {
final ComponentName componentName = mHotseat.getComponentNameByTagIndex(tagIndex);
final String classId = componentName.getClassId();
TwsLog.d(TAG, "getFragmentByTagIndex:" + tagIndex + " classId is " + classId + " will create it(Fragment)");
Fragment fragment = null;
String msg = "";
if (TextUtils.isEmpty(classId)) {
msg = "invalid classId:" + classId + ",请先check这个无效的标识符来源~~~~";
Toast.makeText(this, "getFragmentByTagIndex:" + tagIndex + " return null classId", Toast.LENGTH_LONG)
.show();
} else if (classId.equals(Hotseat.HOST_HOME_FRAGMENT)) {
fragment = mMyWatchFragment = new MyWatchFragmentRevision(mHomeFragementDisplayInfos);
} else {
TwsLog.d(TAG, "getFragmentByPos to get Plugin fragement:" + classId);
Class<?> clazz = null;
if (!TextUtils.isEmpty(componentName.getPluginPackageName())) {
PluginDescriptor pluginDescriptor = PluginManagerHelper.getPluginDescriptorByPluginId(componentName
.getPluginPackageName());
if (pluginDescriptor != null) {
// 插件可能尚未初始化,确保使用前已经初始化
LoadedPlugin plugin = PluginLauncher.instance().startPlugin(pluginDescriptor);
DexClassLoader pluginClassLoader = plugin.pluginClassLoader;
String clazzName = pluginDescriptor.getPluginClassNameById(classId);
if (clazzName != null) {
try {
clazz = ((ClassLoader) pluginClassLoader).loadClass(clazzName);
} catch (ClassNotFoundException e) {
TwsLog.e(TAG, "loadPluginFragmentClassById:" + classId + " ClassNotFound:" + clazzName
+ "Exception", e);
TwsLog.w(TAG, "没有找到:" + clazzName + " 是不是被混淆了~");
}
}
} else {
clazz = PluginLoader.loadPluginFragmentClassById(componentName.getClassId());
}
} else {
clazz = PluginLoader.loadPluginFragmentClassById(componentName.getClassId());
}
if (clazz != null) {
try {
fragment = (Fragment) clazz.newInstance();
} catch (InstantiationException e) {
TwsLog.e(TAG, "InstantiationException", e);
} catch (IllegalAccessException e) {
TwsLog.e(TAG, "IllegalAccessException", e);
}
}
msg = "Not found classId:" + classId + ",请先check提供这个Fragment的插件是否有安装哈(⊙o⊙)~";
}
if (fragment == null) {
fragment = new ToastFragment();
((ToastFragment) fragment).setToastMsg(msg);
}
return fragment;// new Fragment();
}
// 二次解析DisplayConfig
public class DisplayInfo {
public static final int DEFAULT_DISPLAY_LOCATION = 99;
public DisplayInfo(final DisplayConfig dc, final String packageName) {
this.classId = dc.content;
this.componentType = dc.contentType;
// 注意协议对二级pos没配置的默认赋值是-1,这种需要随波逐流,也就是谁先安装谁放前面,谁叫没给配置咧
final int pos = getPosByPackageName(dc.pos, packageName);
if (-1 < pos) {
if (dc.secondPos < 0) {
dc.secondPos = 0;
}
if (POS_WEIGHT <= dc.secondPos) {
dc.secondPos = dc.secondPos % POS_WEIGHT;
}
this.location = pos * POS_WEIGHT + dc.secondPos;
} else {
this.location = DEFAULT_DISPLAY_LOCATION;
}
TwsLog.d(TAG, "==packageName:" + packageName + " title=" + dc.title + " dc.pos=" + dc.pos + " location is "
+ this.location);
if (!TextUtils.isEmpty(dc.title)) {
final String[] titles = dc.title.split(DisplayConfig.SEPARATOR_VALUE);
this.title_en = this.title_zh_CN = this.title_zh_TW = this.title_zh_HK = titles[0];
if (1 < titles.length) {
this.title_en = titles[1];
}
if (2 < titles.length) {
this.title_zh_TW = this.title_zh_HK = titles[2];
}
if (3 < titles.length) {
this.title_zh_TW = titles[3];
}
}
this.statKey = dc.statKey;
if (!TextUtils.isEmpty(dc.iconResName)) {
final String[] resNames = dc.iconResName.split(DisplayConfig.SEPARATOR_VALUE);
this.normalResName = resNames[0];
if (1 < resNames.length) {
this.focusResName = resNames[1];
}
}
this.packageName = packageName;
TwsLog.d(TAG, "DisplayInfo classId=" + this.classId + " location=" + location + " componentType="
+ this.componentType + " title_zh=" + this.title_zh_CN + "/" + this.ab_title_zh_HK + "/"
+ this.ab_title_zh_TW + " normalResName=" + this.normalResName + " focusResName="
+ this.focusResName + " packageName=" + this.packageName);
if (dc.pos == DisplayConfig.DISPLAY_AT_HOTSEAT) {
// actionbar的标题
if (!TextUtils.isEmpty(dc.ab_title)) {
final String[] titles = dc.ab_title.split(DisplayConfig.SEPARATOR_VALUE);
this.ab_title_en = this.ab_title_zh_CN = this.ab_title_zh_TW = this.ab_title_zh_HK = titles[0];
if (1 < titles.length) {
this.ab_title_en = titles[1];
}
if (2 < titles.length) {
this.ab_title_zh_TW = this.ab_title_zh_HK = titles[2];
}
if (3 < titles.length) {
this.ab_title_zh_TW = titles[3];
}
} else {
this.ab_title_en = this.ab_title_zh_CN = this.ab_title_zh_TW = this.ab_title_zh_HK = getResources()
.getString(R.string.app_name);
}
if (!TextUtils.isEmpty(dc.ab_rbtncontent)) {
this.ab_rbtncontent = dc.ab_rbtncontent;
this.ab_rbtnctype = dc.ab_rbtnctype;
if (!TextUtils.isEmpty(dc.ab_rbtnres)) {
final String[] resNames = dc.ab_rbtnres.split(DisplayConfig.SEPARATOR_VALUE);
this.ab_rbtnres_normal = resNames[0];// 是显示文本还是图标由ab_rbtnrestype来决定
if (1 < resNames.length) {
this.ab_rbtnres_focus = resNames[1];
}
}
this.ab_rbtnrestype = dc.ab_rbtnrestype;
} else {
// action 行为都没有 就不处理了
}
TwsLog.d(TAG, "DisplayInfo ab_title_zh=" + this.ab_title_zh_CN + "/" + this.ab_title_zh_HK + "/"
+ this.ab_title_zh_TW + " ab_title_en=" + ab_title_en + " ab_rbtncontent="
+ this.ab_rbtncontent + " ab_rbtnctype=" + this.ab_rbtnctype + " ab_rbtnres_normal="
+ this.ab_rbtnres_normal + " ab_rbtnres_focus=" + this.ab_rbtnres_focus + " ab_rbtnrestype="
+ this.ab_rbtnrestype);
}
}
public String classId = null;
public int componentType;
public CharSequence title_zh_CN = null;
public CharSequence title_zh_TW = null;
public CharSequence title_zh_HK = null;
public CharSequence title_en = null;
public String normalResName = null;
public String focusResName = null;
public String statKey = "";
public String packageName = "";
public int location = 0; // 用于显示的索引位置
public boolean establishedDependOn = true;
// ActionBar
public String ab_title_zh_CN = null;
public String ab_title_zh_TW = null;
public String ab_title_zh_HK = null;
public String ab_title_en = null;
// ActionBar右侧按钮上触发点击后的行为内容
public String ab_rbtncontent = null;
// ActionBar右侧按钮上触发点击后行为的内容类型,同contentType【当前默认是activity,而且也暂时只有activity】
public int ab_rbtnctype = 2;// 默认是activity
// 显示在ActionBar右侧按钮上的内容类型 1、String文本资源 2、图标资源
public int ab_rbtnrestype = 1;
// 显示在ActionBar右侧按钮上的内容,根据类型进行配置
public String ab_rbtnres_normal = null;
public String ab_rbtnres_focus = null;
}
public void initPluginPosFromConfig(int posType) {
String configFile = "";
HashMap<String, Integer> pluginPos;
switch (posType) {
case POS_HOTSEAT:
configFile = POS_HOTSEAT_CONFIG_NAME;
pluginPos = mPluginHotsetPos;
break;
case POS_HOME_FRAGEMENT:
configFile = POS_MYWATCH_CONFIG_NAME;
pluginPos = mPluginMywatchPos;
break;
default:
return;
}
pluginPos.clear();
boolean sucess = false;
Integer pos = 0;
try {
InputStreamReader inputReader = new InputStreamReader(getResources().getAssets().open(configFile));
BufferedReader bufReader = new BufferedReader(inputReader);
String line = "";
while ((line = bufReader.readLine()) != null) {
line = line.trim();
if (TextUtils.isEmpty(line))
continue;
pluginPos.put(line, pos);
++pos;
}
sucess = true;
} catch (Exception e) {
e.printStackTrace();
}
if (!sucess) {
switch (posType) {
case POS_HOTSEAT:
mPluginHotsetPos.clear();
String[] defaultPos_Hotset = getResources().getStringArray(R.array.default_hotset_pos);
pos = 0;
for (String packageName : defaultPos_Hotset) {
packageName = packageName.trim();
if (TextUtils.isEmpty(packageName))
continue;
mPluginHotsetPos.put(packageName, pos);
++pos;
}
break;
case POS_HOME_FRAGEMENT:
mPluginMywatchPos.clear();
String[] defaultPos_Mywatch = getResources().getStringArray(R.array.default_mywatch_pos);
pos = 0;
for (String packageName : defaultPos_Mywatch) {
packageName = packageName.trim();
if (TextUtils.isEmpty(packageName))
continue;
mPluginMywatchPos.put(packageName, pos);
++pos;
}
break;
default:
break;
}
}
}
private int getPosByPackageName(int posType, String packageName) {
switch (posType) {
case POS_HOTSEAT:
if (mPluginHotsetPos.containsKey(packageName)) {
return mPluginHotsetPos.get(packageName);
}
return -1;
case POS_HOME_FRAGEMENT:
if (mPluginMywatchPos.containsKey(packageName)) {
return mPluginMywatchPos.get(packageName);
}
return -1;
default:
return -1;
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// 当前不对mFragments进行状态保存[恢复的时候状态错乱了],在这里通过mCurrentPage来保存并进行恢复
if (outState != null) {
outState.remove(FRAGMENTS_TAG);
}
}
@Override
public void switchToFragment(String classId, int extras) {
if (mHotseat == null) {
TwsLog.e(TAG, "switchToFragment:" + classId + " Failed for mHotseat is null");
return;
}
mHotseat.switchToFragment(classId, extras);
}
@Override
public void setHighlightCellItem(String classId, boolean needHighlight) {
if (mHotseat == null) {
TwsLog.e(TAG, "setHighlightCellItem:" + classId + " Failed for mHotseat is null");
return;
}
mHotseat.setHighlightCellItem(classId, needHighlight);
}
@Override
public Context getHostFitContext() {
return this;
}
}